package api

import (
	"context"
	"crypto/rand"                                         // 用于生成安全随机数
	"fmt"                                                 // 标准库输出
	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests" // 阿里云 SDK 的通用请求
	"go-likaladi-shop/common/base_global"
	"go.uber.org/zap" // zap 日志库
	"math/big"        // 处理大数字和随机数生成
	"time"
)

func getSmsRequest() *requests.CommonRequest {
	// 创建一个通用请求对象
	// 相比于 `dysmsapi.CreateSendSmsRequest()`，这种方式更灵活，但字段需要自己处理
	request := requests.NewCommonRequest()

	// 设置请求方式为 POST
	request.Method = "POST"

	// 设置请求协议为 HTTPS（也可以是 HTTP，不推荐）
	request.Scheme = "https"

	// 设置阿里云短信服务的域名（固定值）
	request.Domain = "dysmsapi.aliyuncs.com"

	// 设置 API 版本（官方文档推荐使用的版本）
	request.Version = "2017-05-25"

	return request
}

// SendSMS 发送短信验证码
// 通过阿里云的短信服务 dysmsapi 实现
func SendSMS(phone string) {
	request := getSmsRequest()

	// 设置调用的 API 名称
	request.ApiName = "SendSms"

	// ===== 必填参数设置 =====
	// 1. 目标手机号，支持批量发送（逗号分隔），这里只演示一个手机号
	request.QueryParams["PhoneNumbers"] = phone // TODO: 替换为接收验证码的真实手机号

	// 2. 签名名称，必须在阿里云短信控制台已备案并审核通过
	request.QueryParams["SignName"] = "你的短信签名" // TODO: 替换为你的短信签名

	// 3. 模板 CODE，阿里云短信模板的编号（在控制台创建后获得）
	request.QueryParams["TemplateCode"] = "SMS_1234567" // TODO: 替换为你的模板 CODE

	// 4. 模板参数，按模板的格式传入 json 字符串
	// 例如：模板内容为 "您的验证码为 ${code}"，则传 {"code":"123456"}
	code := GenerateSmsCode(6) // 生成 6 位数字验证码
	request.QueryParams["TemplateParam"] = "{\"code\":\"" + code + "\"}"

	// 发送请求到阿里云短信服务
	response, err := base_global.AliSmsClient.ProcessCommonRequest(request)
	if err != nil {
		// 请求失败，记录错误日志
		zap.S().Error("阿里云短信发送失败：", err.Error())
		return
	}

	// 打印短信发送响应内容（也可以记录到日志）
	fmt.Printf("短信发送返回: %s\n", response.GetHttpContentString())

	// TODO: 这里可以将验证码存储到 Redis，供后续验证使用（例如 global.RdbCluster.Set...）
	base_global.RdbCluster.Set(context.Background(), phone, response.GetHttpContentString(), 60*time.Second)
}

// GenerateSmsCode 生成随机的短信验证码
// 使用 crypto/rand 保证随机性更安全，不容易被猜测
// 参数：length 验证码长度（通常是 6 位）
// 返回值：生成的验证码字符串
func GenerateSmsCode(length int) string {
	code := "" // 最终验证码字符串
	for i := 0; i < length; i++ {
		// 生成 [0-9] 范围的随机数
		// big.NewInt(10)：表示随机范围是 0-9
		n, _ := rand.Int(rand.Reader, big.NewInt(10))

		// 转换为字符串追加到 code
		code += n.String()
	}
	return code
}
